#ifndef JOUEUR_H
#define JOUEUR_H

#include "ADD.h"
#include <map>
using namespace std;

/**
 * @addtogroup Utilitaires
 * @{
 */

/**
 * Sert à énumérer les différents types de classes multiples.
 */
enum TypeMulti
  {
    Non, /**< Le Joueur n'a qu'une classe */
    Mul, /**< Le Joueur est multiclassé*/
    Jum /**< Le Joueur a jumelé */
  };

/**
 * Enumère les Dons / Désavantages
 */
enum TypeComp  {Don, Desav};

/**
 * \}
 */

void OutputLevel();

/**
 * Cette classe permet la création de la feuille de perso. Un Joueur possède
 * une Race, une (ou plusieurs) Classe. Depuis Joueur il est possible
 * décire un fichier XML, d'en lire et finalement de produire le code
 * LaTeX qui fera une jolie feuille de personnage. Le Joueur est en fait
 * l'implémentation du PJ.
 *
 * Joueur est aussi un parseur XML. C'est n'est pas très joli au point de vue
 * de l'implémentation, un encapsulation serait préférable... Les fonctions
 * élémentaires liées au parseur ne sont pas présente dans cette documentation.
 * @author Johan "Solo" Luisier
 */
class Joueur
{
 public:
  /**
   * Le constructeur par défaut fait appel au chargement d'un Joueur depuis
   * un fichier .xml
   */
  Joueur();
  /**
   * Ce constructeur sert lors de la création d'un nouveau Joueur, une fois
   * que la Classe et la Race sont créés.
   * @param classe Classe du Joueur (première Classe si multiclassé)
   * @param race Race du Joueur
   * @param nom Nom du Joueur
   */
  Joueur(Classe* classe, Race* race, const string& nom);
  /**
   * Destructeur, qui gère la libération de la mémoire allouée
   */
  ~Joueur();
  /****************************************************************************
   *
   * Méthodes
   *
   ***************************************************************************/
  /**
   * Affiche le nom, la race et la (les) classes
   */
  void information();
  /**
   * Demande à l'utilisateur d'entrer le nom du fichier à ouvrir
   * @return nom du fichier (string)
   */
  string demander_nom() const;
  /**
   * Sauve le Joueur dans un fichier .xml
   */
  void ecrire_xml() const;
  /**
   * Permet de fixer le nombre de pp
   * @param pps nombre de pp
   */
  void set_pp(const unsigned int& pps);
  /**
   * Permet de fixer le nombre de pts de vie
   * @param pv nombre de pts de vie
   */
  void set_pv(const unsigned int& pv);
  /**
   * Permet d'ajouter une classe, lors de la création d'un Joueur multiclassé
   * ou lors du jumelage
   */
  void ajout_classe(Classe* classe);
  /**
   * Prépare la sortie en .tex, càd crée tous les fichiers nécessaires
   */
  void ecrire_tex() const;
  /**
   * Retrouve le nombre de dons du personnage
   * @return taille de J_Dons (unsigned int)
   */
  unsigned int get_combien_dons() const;
  /**
   * Retrouve le nombre de désavantages du personnage
   * @return taille de J_Desavantages (unsigned int)
   */
  unsigned int get_combien_desavantages() const;
  /**
   * Retrouve le nombre de compétences diverses du personnage
   * @return taille de J_CompDiv (unsigned int)
   */
  unsigned int get_combien_competences() const;
  /**
   * Retrouve le nombre de compétences martiales du personnage
   * @return taille de J_Martiales (unsigned int)
   */
  unsigned int get_combien_comp_martiales() const;
  /**
   * Fixe les niveaux de sortie des différentes méthodes
   * @param level niveau de sortie
   * @param n choix de la variable
   */
  static void setLevel(const DebugLevelType& level, const unsigned int& n);
  /**
   * Regarde si le Joueur possède des sorts de mage (=> mage, spécialiste,
   * barde avec compétence) et remplit vec avec les pointeurs sur les classe
   * possédant de tels sorts
   * @param vec pointeur sur le conteneur de pointeurs sur les 
   * "Livres de Sorts"
   * @return le Nom du Joueur
   */
  string a_sorts_mage(vector<Classe *>& vec) const;

  /****************************************************************************
   *
   * Fonctions de gestion de l'évolution du Joueur
   *
   ***************************************************************************/

  /**
   * Détermine les dons et désavantages du personnage, lors de la création.
   */
  void determiner_dons_desavantages(const TypeComp& quoi);
  /**
   * Détermine le choix des compétences diverses du personnage, lors de
   * la création ou du passage de niveau.
   */
  void determiner_competences();
  /**
   * Permet d'améliorer une compétence à la création ou au passage de niveau
   */
  void augmenter_competences();
  /**
   * Détermine les compétences martiales, à la création ou au passage de
   * niveau du personnage.
   */
  void determiner_comp_martiales();
  /**
   * Augmente le total de pts d'expérience.
   * @param xp pts d'expériences gagnés
   */
  void ajouter_xp(const unsigned int& xp);
  /**
   * Augmente les pps disponibles
   * @param pp pp gagnés
   */
  void ajouter_pp(const unsigned int& pp);
  /**
   * Augmente le total de pts de vie
   * @param pv pts de vie suppléentaires
   */
  void ajouter_pv(const unsigned int& pv);

 protected:
  /**
   * Nom du personnage
   */
  string Nom;
  /**
   * Contient la (les) classe(s) du personnage
   * @see Classe
   */
  vector< Classe* > J_classe;
  /**
   * Contient la race du personnage
   * @see Race
   */
  Race* J_race;
  unsigned int TAc0, /**< TAC0 du personnage */
    PV, /**< Nombre de pts de vie */
    PP, /**< Nombre de pp restant */
    nb_classes; /**< Nombre de classes (dimension de J_classe) */
  /**
   * Classe d'armure
   */
  int CA;
  vector<unsigned int> J_CompDiv, /**< Compétences diverses */
    J_Dons, /**< Dons */
    J_Desavantages, /**< Désavantages */
    J_Martiales; /**< Compétences martiales */
  /**
   * Compétences diverses accessibles (Roublard, Combattant, etc...)
   */
  vector<TypeClasse> J_CompAccess;
 
  /****************************************************************************
   *
   * Niveaux de sortie des sous-fonctions
   * 'static', toujours par soucis d'optimisation
   *
   ***************************************************************************/

  /**
   * Niveau de sortie basique pour la gestion du XML.
   */
  static DebugLevelType fonction_elementaire_xml;
  /**
   * Niveau de sortie pour les fonctions de récupération d'information
   * à partir du XML.
   */
  static DebugLevelType fonction_recuperation_xml;
  /**
   * Niveau de sortie des fonctions écrivant les sources .tex.
   */
  static DebugLevelType fonction_tex;
  /**
   * Niveau de sortie pour les autres fonctions.
   */
  static DebugLevelType interne;

 private:
  /****************************************************************************
   *
   * Ajustements dus aux traits, sont stockés sous forme de tableaux 'static'
   * par soucis d'optimisation.
   *
   ***************************************************************************/

  /**
   * Ajustements au toucher, aux dégâts, charge autorisée, charge maximale,
   * défoncer portes, barreaux & herses.
   */
  static const string Aj_Force[30][6];
  /**
   * Ajustement réflexe, ajustement aux missiles, ajustement défensif.
   */
  static const string Aj_Dexterite[14][3];
  /**
   * Ajustement au PV, choc métabolique, régénération, survie à la
   * résurection, ajustement aux JS contre les Poisons.
   */
  static const string Aj_Const[25][5];
  /**
   * Nombre de langues, niveau de sort maximal, pourcentage d'apprentissage
   * de sorts, nombre maximal de sort par niveau, immunité aux illusions.
   */
  static const string Aj_Int[19][5];
  /**
   * Bonus aux JS contre les sorts mentaux, sorts bonus, pourcentage d'échec
   * des sorts, immunité aux sorts.
   */
  static const string Aj_Sagesse[24][4];
  /**
   * Nombre de compagnon d'arme, loyauté inspirée, bonus à la réaction.
   */
  static const string Aj_Charisme[24][3];

  /****************************************************************************
   *
   * Dons, désavantages et compétences non-martiales
   * 'static', toujours par soucis d'optimisation
   *
   ***************************************************************************/

  static const ListCapa Dons[27], /**< Liste des dons @see ListCapa */
    Desavantages[38]; /**< Liste des désavantages @see ListCapa */

  /**
   * Liste des compétences diverses.
   * @see ListNonMart
   */
  static const ListNonMart CompetencesDiverses[85];

  /**
   * Liste des catégories de compétences diverses (Générale, Combattant, ...).
   */
  static const string CategoriesCompetences[5];

  /**
   * Liste des compétences martiales disponibles pour chaque classe
   * 'static', toujours par soucis d'optimisation.
   *
   * Pour chaque classe on garde la position dans CompMartialesParClasse
   * de sa liste d'armes.
   */
  static const map<string, unsigned int> GererClasses;

  /**
   * Ce tableau contient des pointeurs vers les listes d'armes
   * disponibles pour chaque type de classe.
   *
   * Les combattants ont accès à toutes les armes, alors on ne déclare pas
   * de variables pour eux, et CompMartialesParClasse contient 0 pour
   * ces classes.
   */
  static const vector<unsigned int>* CompMartialesParClasse[5];

  /*
   * Mages et Spécialistes on la même sélection d'armes => un seul tableau
   * mais deux pointeurs dans CompMartialesParClasse.
   */
  static const vector<unsigned int> CompMarMage, CompMarClerc, CompMarDruide,
    CompMarVoleur;

  /**
   * Gestion de la mémoire allouée dynamiquement.
   */
  bool libere_mem;
  /**
   * Gestion de multiclassé ou classes jumelées (=> gestion des XPs).
   * @see TypeMulti
   */
  TypeMulti TM_switch;
  /**
   * Modifie les PP alloués au Joueur, selon son score lors de la création.
   */
  void modificateur_PP();
  /**
   * Ajuste la valeur d'une compétence en fonction du trait associé.
   * @param val valeur de base de la compétence
   * @param trait valeur du trait associé
   */
  void modificateur_val(unsigned int& val, const unsigned int& trait);
  /**
   * Retourne le nom sous forme d'une string "simplifiée" => sans " " ni ',
   * afin de créer le dossier contenant les feuilles de perso.
   */
  string convert_nom() const;
  /**
   * Enlève les doublons dans J_CompAccess
   */
  void nettoie_TC();

  /****************************************************************************
   *
   * Sous-fonctions qui écrivent les différentes parties du code .tex
   * nécessaire pour la feuille complète.
   *
   ***************************************************************************/

  void ecrire_traits_tex() const;
  void ecrire_JS_tex() const;
  void ecrire_scores_tex() const;
  void ecrire_race_tex() const;
  void ecrire_classe_tex() const;
  void ecrire_comp_tex() const;
  void ecrire_sorts_tex() const;


  /****************************************************************************
   *
   * Fonctions XML
   *
   ***************************************************************************/
  int index;
  // Position de lecture du fichier .xml
  void trouver_o (string&);
  // Cherche le caractere <, en fonction de la derniere position de lecture
  void trouver_f (string&);
  // Cherche le caractère >, en fonction de la derniere position de lecture (?)
  int trouver_o_I (string&);
  // Cherche le caractere > qui indique la fin d une balise
  int trouver_f_I (string&);
  // Cherche le caractere > qui indique la fin d une balise
  void sauter_blanc(string&);
  // Avance l'index de lecture jusqu'au moment ou y a plus de blancs
  // (caractere vide)
  void wipe_blank(string& a);
  // Enlève les blancs ' ' à la fin d'une string
  string lit_balise(string&,char&);
  // Lit et renvoie le contenu d'une balise
  void skip_comment(string&);
  // Saute les parties commentées <!-- -->
  bool verifier_contenu_futur(string& a, string& b);
  // Lit le contenu de la prochaine balise et le compare avec la chaine b
  int read_int(string&);
  // Lit un int et le renvoie
  int translate(char);
  // Traduit un char en int
  bool c_un_chiffre(char);
  // Vérifie que l'on est bien en train de lire un caractère numérique

  /****************************************************************************
   *
   * Méthodes de récupérations des infos
   *
   ***************************************************************************/
  void trouver_interpreter_ecrire_joueur(string&);
  // Effectue la lecture du fichier .xml, écrit le Joueur
  void trouver_interpreter_ecrire_typeRace(string&);
  // Gestion de la Race du Joueur
  void trouver_interpreter_ecrire_typeClasse(string&, unsigned int tab[7]);
  // Gestion d'une Classe du Joueur

  string trouver_interpreter_ecrire_nom(string&);
  string trouver_interpreter_ecrire_race(string&);
  string trouver_interpreter_ecrire_classe(string&);
  // Retrouvent la string qui indique le Nom, la Race et la Classe

  void trouver_interpreter_ecrire_capacites(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_traits(string&, unsigned int tab[7]);
  void trouver_interpreter_ecrire_competences(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_dons(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_desavantages(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_nonmart(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_martiales(string&, vector<unsigned int>&);
  void trouver_interpreter_ecrire_sorts(string&, vector<Sort>&);
  void trouver_interpreter_ecrire_access(string&);
  // Retrouvent les capacités raciales, les traits et les compétences
  // de classe, les sorts (de type mage) et les accès aux comp. diverses

  int trouver_interpreter_ecrire_nb(string&);
  int trouver_interpreter_ecrire_PV(string&);
  int trouver_interpreter_ecrire_PP(string&);
  int trouver_interpreter_ecrire_XP(string&);
  // Retrouvent le nombre de classe, le nbr de PV, de PP et les XP
};

#endif
